<template>
  <el-dialog
    top="50px"
    width="800px"
    :title="title"
    append-to-body
    class="dialog-sm"
    :close-on-click-modal="false"
    :visible.sync="visible"
    :before-close="beforeClose"
  >
    <div class="border rounded">
      <div
        class="attach-upload-container"
        :class="{ 'is-dragover': dragover }"
        @drop.prevent="onDrop"
        @dragover.prevent="onDragover"
        @dragleave.prevent="dragover = false"
      >
        <div class="row">
          <div class="col-3" v-for="(file, index) in attachList" :key="index">
            <div class="attach-upload-item" :class="{ disabled: loading }">
              <div class="aui-view">
                <img
                  v-if="file.viewType === 'image'"
                  :src="file.attachment || file.url"
                  :alt="file.labelKey"
                  class="aui-view-img"
                />
                <i v-else class="fa aui-view-icon" :class="file.viewIcon"></i>
              </div>
              <div class="aui-action-mask"></div>
              <div class="aui-action">
                <div class="aui-action-btns">
                  <el-button
                    v-if="file.viewType === 'image'"
                    round
                    icon="el-icon-zoom-in"
                    @click="handlePreviewFile(index)"
                  ></el-button>
                  <el-button v-else round @click="handleLinkFile(index)">
                    <i class="fa fa-external-link"></i>
                  </el-button>
                  <!-- <a :href="file.attachment"
                     charset="UTF-8"
                     target="_blank"> <i class="fa fa-external-link"></i></a> -->
                  <el-button
                    round
                    icon="el-icon-delete"
                    @click="deleteData(file.id, file.attachment)"
                  ></el-button>
                </div>
              </div>
              <div v-if="file.loading" class="aui-percent-loading">
                <i class="el-icon-loading"></i>
              </div>
              <div class="aui-name">
                <div class="aui-name-bg"></div>
                <div class="aui-name-percent" :style="{ width: `${file.percent}%` }"></div>
                <el-button type="text" @click="handleChangeLabel(file.id)" class="aui-name-text">
                  {{ file.labelKey || file.name }}
                </el-button>
              </div>
            </div>
          </div>

          <div class="col-3">
            <div class="attach-upload-item">
              <input
                type="file"
                ref="uploadInput"
                class="d-none"
                multiple
                @change="handleFileChange"
              />
              <el-button class="attach-upload-btn" :disabled="loading" @click="handleSelectFile">
                <i class="el-icon-upload attach-upload-btn-icon"></i>
                <div class="attach-upload-btn-text">点击上传</div>
                <div class="text-muted">或将文件拖到此处</div>
              </el-button>
            </div>
          </div>
        </div>
      </div>

      <el-dialog
        append-to-body
        center
        title="选择附件标签"
        width="360px"
        :close-on-click-modal="false"
        :before-close="handleDialogClose"
        :visible.sync="labelDialogVisible"
      >
        <div>
          <el-tag
            v-for="(item, index) in tags"
            style="margin-left: 10px; margin-top: 5px"
            :disable-transitions="false"
            :key="index"
          >
            <el-button size="mini" type="text" @click="handleSelectLabel(item)">
              {{ item }}
            </el-button>
          </el-tag>

          <el-input
            v-if="inputVisible"
            v-model="inputValue"
            class="input-new-tag"
            ref="saveTagInput"
            size="small"
            style="margin-left: 10px; margin-top: 5px; width: 120px"
            @blur="handleInputConfirm"
            @keyup.enter.native="handleInputConfirm"
          ></el-input>

          <el-button
            v-else
            class="button-new-tag"
            size="small"
            style="margin-left: 10px; margin-top: 5px"
            @click="showInput"
          >
            + 自定义标签
          </el-button>
        </div>
      </el-dialog>
    </div>
  </el-dialog>
</template>

<script>
import { arrayFromString } from '@vimi/utils-tool'
import { attachAdapter, fileAdapter } from '@/bank/components/attach/index'
import { deleteOss, uploadOss } from '@/common/api/oss'
export default {
  props: {
    title: {
      type: String,
      default: '附件上传',
    },
    // 默认上传标签，如果存在，则不用选择标签
    defaultTag: String,
    visible: Boolean,
    customerRelatedId: { type: String, default: '' },
  },
  data() {
    return {
      fileList: [],
      uploadFiles: [],
      defaultTags: ['生产条件', '生产设施', '基础设施', '其它', '周边环境'],
      tags: [],
      loading: false,
      dragover: false,
      tableName: 'datum_customer_attachment',
      labelDialogVisible: false,
      selectId: '',
      selectKey: '',
      saveLoading: false,
      inputValue: '',
      inputVisible: false,
    }
  },

  watch: {
    customerRelatedId() {
      this.getData()
    },
  },
  computed: {
    fileCount() {
      return this.uploadFiles.length
    },
    attachList() {
      return [...this.fileList, ...this.uploadFiles]
    },
  },
  created() {
    this.tags = [...this.defaultTags]
  },
  methods: {
    async getData() {
      this.fileList = []
      if (!this.customerRelatedId) {
        return
      }

      this.loading = true
      const [res, err] = await this.$utils.promise(
        this.$api.getData(
          'credit',
          this.tableName,
          {
            'customer_related_id.eq': this.customerRelatedId,
          },
          { create_time: 'asc' }
        )
      )
      this.loading = false

      if (err) {
        return this.$message.error('获取附件失败，请重试！')
      }
      const data = res?.data ?? []
      data.forEach(item => {
        const urls = arrayFromString(item.attachment)
        for (const url of urls) {
          this.fileList.push(
            attachAdapter({
              id: item.id,
              labelKey: item.attachment_type || item.remark || '其他',
              attachment: url,
              remark: item.remark,
            })
          )
        }
      })
    },
    handleFileChange(e) {
      const { files = [] } = e.target

      for (let i = 0; i < files.length; i++) {
        const file = files[i]
        if (!file.type) {
          continue
        }
        this.uploadFiles.push(fileAdapter(file))
        this.tags.push(file.name.replace(/(\..*)$/g, ''))
      }
      if (this.fileCount > 0) {
        this.labelDialogVisible = true
      }
      this.handleClear()
    },
    handleSelectFile() {
      if (!this.customerRelatedId) {
        return this.$message.error('没有项目附件的相关信息，不能上传附件')
      }

      const { uploadInput } = this.$refs
      uploadInput.click()
    },
    handleClear() {
      const { uploadInput } = this.$refs
      uploadInput.value = ''
    },

    handlePreviewFile(index) {
      const { attachment, labelKey } = this.attachList[index]
      this.$utils.viewer({
        images: [{ url: attachment, name: labelKey }],
      })
    },

    handleLinkFile(index) {
      const { attachment } = this.attachList[index]
      window.open(attachment, '_blank')
    },
    // 拖拽上传
    onDragover() {
      if (!this.loading) {
        this.dragover = true
      }
    },

    // 拖拽放下
    onDrop(e) {
      if (this.loading) return
      this.dragover = false

      const { files } = e.dataTransfer
      for (let i = 0; i < files.length; i++) {
        const file = files[i]
        if (!file.type) {
          continue
        }
        // 过滤类型
        this.uploadFiles.push(fileAdapter(file))
      }
      if (this.fileCount > 0) {
        this.labelDialogVisible = true
      }
      this.handleClear()
    },
    deleteData(id, url) {
      const h = this.$createElement
      this.$msgbox({
        title: '提示',
        message: h('span', undefined, `确定删除该附件？`),
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        beforeClose: async (action, instance, done) => {
          if (action === 'confirm') {
            instance.confirmButtonLoading = true
            instance.confirmButtonText = '删除中...'
            const [res] = await this.$utils.promise(
              this.$api.deleteData('credit', this.tableName, id)
            )
            deleteOss(url)
            instance.confirmButtonLoading = false
            instance.confirmButtonText = '确定'
            if (res) {
              this.$message.success('删除成功！')
              this.getData()
              done()
            } else {
              this.$message.error('删除失败，请重试！')
            }
          } else {
            done()
          }
        },
      }).catch(() => {})
    },
    beforeClose() {
      this.$emit('update:visible', false)
    },
    handleSelectLabel(labelKey) {
      this.selectKey = labelKey
      if (this.selectId) {
        this.putLabelData()
      } else {
        this.uploadFiles = this.uploadFiles.map(item => {
          item.labelKey = labelKey
          return item
        })
        this.handleUploadFile()
      }
      this.labelDialogVisible = false
    },
    // 上传OSS
    async handleUploadFile() {
      const { fileCount, uploadFiles } = this

      if (fileCount === 0) {
        return this.$message.error('请先选择文件')
      }

      const promises = uploadFiles.map(it =>
        uploadOss({
          file: it.file,
          dir: `credit/attach/${this.customerRelatedId}`,
          type: 1,
          progress: ({ percent }) => {
            it.percent = percent
            it.loading = percent < 100
          },
        })
      )

      this.loading = true
      return Promise.all(promises)
        .then(list => {
          const attachData = list.map((url, index) => {
            const { viewType, name } = uploadFiles[index]
            return {
              attachment: url,
              attachment_type: this.selectKey,
              customer_related_id: this.customerRelatedId,
              file_type: viewType === 'image' ? 1 : 2,
              remark: name,
            }
          })
          return this.addData(attachData).then(res => ({ res, list }))
        })
        .then(res => {
          this.getData()
          this.uploadFiles = []
          this.$emit('success', res)
          this.handleDialogClose()
        })
        .finally(() => {
          this.loading = false
        })
    },

    // 添加附件表
    async addData(data) {
      return this.$api.addBatch('credit', this.tableName, data)
    },
    async putLabelData() {
      this.saveLoading = true
      const [res] = await this.$utils.promise(
        this.$api.updateData('credit', this.tableName, this.selectId, {
          attachment_type: this.selectKey,
        })
      )
      this.saveLoading = false
      if (res) {
        this.handleDialogClose()
        this.$message.success('修改成功！')
        this.getData()
      } else {
        this.$message.error('修改附件失败，请重试！')
      }
    },
    handleChangeLabel(id) {
      this.selectId = id
      this.labelDialogVisible = true
    },
    handleInputConfirm() {
      let inputValue = this.inputValue
      if (inputValue) {
        this.tags.push(inputValue)
      }
      this.inputVisible = false
      this.inputValue = ''
    },
    showInput() {
      this.inputVisible = true
      this.$nextTick(() => {
        this.$refs.saveTagInput.$refs.input.focus()
      })
    },
    handleDialogClose() {
      this.tags = [...this.defaultTags]
      this.uploadFiles = []
      this.selectId = ''
      this.selectKey = ''
      this.labelDialogVisible = false
    },
  },
}
</script>

<style lang="scss" scoped>
.text-sm {
  font-size: 0.875rem;
}

.attach-upload-action {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid $border-color;
  padding: 0.5rem 1rem;
}

.attach-upload-container {
  width: 100%;
  height: 50vh;
  overflow-y: auto;
  padding-top: 0.5rem;
  padding: 0.5rem;
  padding-left: $grid-gutter-width;
  padding-right: $grid-gutter-width;
  transition: background-color 0.1s;

  @include scrollbar-theme();

  &.is-dragover {
    background-color: $primary-light-9;
    background-color: var(--primary-light-9);

    .attach-upload-item .el-button {
      background-color: $primary-light-9;
      background-color: var(--primary-light-9);
    }
  }
}

.attach-upload-item {
  position: relative;
  overflow: hidden;
  height: 136px;
  margin: 0.5rem 0;
  border: 1px solid $gray-200;
  border-radius: 0.25rem;

  &.disabled {
    cursor: not-allowed;
  }

  &:not(.disabled):hover {
    .aui-action {
      display: block;
    }
    .aui-action-mask {
      opacity: 1;
    }
  }
}

.aui-name {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 26px;

  &-text {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 2px 0.5rem;
    color: #fff;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &-bg {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.4);
  }

  &-percent {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 100%;
    background-color: $primary;
  }
}

.aui-view {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  &-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  &-icon {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -68%);
    font-size: 3.6rem;
    color: $gray-600;
  }
}

.aui-action {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%);
  display: none;

  &-btns {
    position: absolute;
    top: 50%;
    width: 100%;
    transform: translateY(-68%);
    display: flex;
    justify-content: center;
  }
}

.aui-action-mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);
  opacity: 0;
  transition: all 0.3s;
}

.aui-percent-loading {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.9);
  padding-top: 20%;
  text-align: center;
  color: $gray-500;
  font-size: 3rem;
}

.attach-upload-btn {
  width: 100%;
  height: 100%;
  border-radius: 0.1rem;
  border: none;
  color: $primary;
  color: var(--primary);

  &-icon {
    font-size: 4rem;
    color: $gray-500;
    margin-bottom: 0.5rem;
  }

  &:disabled {
    color: $gray-500;
    cursor: not-allowed;
  }
}
</style>
